
package docmodel;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;

import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.stream.StreamResult;

import jlibs.xml.xsd.XSDocument;
import jlibs.xml.xsd.XSDocument.Compositor;

import org.apache.xerces.parsers.DOMParser;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import utils.File_Utils;

/**
 * 
 */
public class XsdTool 
{
	/** */
	private DOMParser parser;
	
	/** */
	private Document doc;
	
	//-----------------------------------------
	/** */
	private XSDocument xsd;
	
	/** */
	private FileOutputStream out;
	//-----------------------------------------
	
	/** */
	private XDP_Liste liste;						
					
	/** */
	private String input_file;
	
	/** */
	private String output_file;
	
	/** */
	private String output_file_name_only;
		
	public String getOutput_file_name_only() {
		return output_file_name_only;
	}

	/** */
	private boolean dataPDF_FLAG = false;
	
	/** */
	private String type_prova = "";
	
	/**
	 *  COSTRUTTORE 1
	 *  
	 * @param reader
	 */
	public XsdTool(XDP_Reader reader) 
	{
		parser 		= reader.getParser();
		doc	  		= reader.getDocument();
		liste  		= reader.getListe();
		input_file  = reader.getInputFile();
		
		output_file_name_only = File_Utils.stripExtension(input_file);
		output_file 		  = output_file_name_only + ".xsd";
		
		try 
		{
			out	 = new FileOutputStream(output_file);
		}
		catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * COSTRUTTORE 2 - per il main
	 * 
	 */
	public XsdTool(String inputFile) 
	{
		 System.err.println("Xsd Tool: costruttore sbagliato!");
	}


	private void getXDPData () 
	{	
		//1
			//getDataPdf();																			///XXX staccato!
		
		//2
		
		//
	}
	
	/**
	 * 
	 * @param xsd_file
	 * @throws TransformerConfigurationException
	 * @throws SAXException
	 * @throws FileNotFoundException 
	 */
	private void write_xsd() throws TransformerConfigurationException, SAXException, FileNotFoundException 
	{
		
		xsd = new XSDocument(new StreamResult(out), false, 4, null);						 
		
		//Result  "result" 
		//boolean "omitXMLDeclaration"
		//int 	  "indentAmount"
		//String  "encoding"
				
		xsd.startDocument();
		{
//		    String _tct_ = output_file_name_only;		    
		    String _xsd_ = output_file_name_only;
		    
//		    xsd.xml().declarePrefix("tct", _tct_); //xsd.xml().declarePrefix("tct", xsd_file);
//		    xsd.xml().declarePrefix("xsd", "http://www.w3.org/2001/XMLSchema");
//		    xsd.xml().declarePrefix("xsd");
		    
		    xsd.startSchema(null); //  <xsd:schema [targetNamespace="$targetNamespace"]>
		    xsd.xml().addAttribute("targetNamespace",output_file_name_only );
		    {
		    	//ROOT  
		        xsd.startElement().name("root");
		        
		        //Complex Type
		        xsd.startComplexType();
		        
		        //Compositor CHOICE
		        xsd.startCompositor(Compositor.CHOICE).occurs(0, -1);

		        //----------- infoPDF -------------
		        xsd.startElement().name("infoPDF");
		        {
		        	add_infoPDF(xsd);																    //FUNCT
		        }
		        xsd.endElement();
		        
		        //----------- startPDF -------------
		        xsd.startElement().name("startPDF");		
		        {
		        	add_dataPDF(xsd);																	//FUNCT
			        //----------- floatingFIELD --------
			        add_FloatingFields(xsd);														        //FUNCT	
			        //----------------------------------

		        }
		        xsd.endElement();
		        //----------------------------------
		        
		        xsd.endCompositor();  //Compositor CHOICE
		        xsd.endComplexType(); //Complex Type
		        		        
		        
		        xsd.endElement(); //root END												//spostare SU
		    }
		    xsd.endSchema();
		}
		xsd.endDocument();
	}
	
	/**
	 * 
	 * @param xsd
	 * @throws SAXException 
	 */
	private void add_dataPDF(XSDocument xsd) throws SAXException 
	{
    	//xsd.startComplexType();
    	
    	for(String elem_name : liste.listaDataPDF) 
		{	
    		xsd.startElement().name(elem_name) .type(type_prova, "xsd:string").endElement(); 
		}
        
    	//xsd.endComplexType();
	}
	/**
	 * 
	 * @param xsd
	 * @throws SAXException 
	 */
	private void add_infoPDF(XSDocument xsd) throws SAXException 
	{        	
		xsd.startComplexType();		  
        xsd.startCompositor(Compositor.SEQUENCE);

        xsd.startElement().name("app")		.type(type_prova, "xsd:string").endElement();
        xsd.startElement().name("template") .type(type_prova, "xsd:string").endElement();
        xsd.startElement().name("version")  .type(type_prova, "xsd:string").endElement();
        xsd.startElement().name("data")     .type(type_prova, "xsd:date").endElement();
        xsd.startElement().name("out")      .type(type_prova, "xsd:string").endElement();

        xsd.endCompositor();	
        xsd.endComplexType();
	}
	
	/**
	 * 
	 * @param xsd
	 * @throws SAXException
	 */
	private void add_FloatingFields(XSDocument xsd) throws SAXException  
	{
		
		xsd.startComplexType();
        xsd.startCompositor(Compositor.SEQUENCE);
        
        //P
        //liste.stampa_lista();
        
		for (Field ff : liste.listaFields) {
			add_floatingfield_element(ff,xsd);
		}
		
		xsd.endCompositor();
	    xsd.endComplexType();
	}
	
	
	/**
	 * 
	 * @param xsd
	 * @throws SAXException 
	 */
	private void add_floatingfield_element(Field ff, XSDocument xsd) throws SAXException 
	{
    	xsd.startElement().name(ff.getName()).type(type_prova, "xsd:string").endElement();//<xsd:element name="floatingField" type="xsd:string"/>
    	//xsd.startElement().name("floatingField").type("xsd:", "string").endElement();      //<xsd:element  name="floatingField" type="ns:string" xmlns:ns="xsd:"/>     	            
	}
	
	
	//-----------------------------------------------------------------------------------------------------------------------------------------------
	
	private void walkNode(NodeList elements)  
	{
	   
		//
		NodeList children = elements;
	
	    for (int i = 0; i < children.getLength(); i++) 
	    {
	    	Node aNode = children.item(i);
				    	
	    	if (aNode.hasChildNodes())
	    		walkNode(aNode);
	    	else
	    		printNode(aNode);
	    }
	     
	}
	
	private void walkNode(Node theNode) 
	{

	    NodeList children = theNode.getChildNodes();

	    //
	    printNode(theNode);
	    
	    for (int i = 0; i < children.getLength(); i++) 
	    {
	    	Node aNode = children.item(i);
	    	
	    	//------------------------------------------------
	    	if(dataPDF_FLAG) 
	    	{
	    		String node_name = aNode.getNodeName();
	    		String text = "#text";
	    	    
	    	    if(!node_name.equals(text))
	    	    	liste.aggiungi_dataPDF_Element(node_name);
	    	}
	    	//------------------------------------------------
	    	
	    	if (aNode.hasChildNodes())
	    		walkNode(aNode);
	    	else
	    		printNode(aNode);
	    }
	    
	 }
	 
	 private void printNode(Node aNode) 
	 {
		 //System.out.println(aNode.getNodeName() + "," + aNode.getNodeValue());
	 }
	 
	 //-----------------------------------------------------------------------------------------------------------------------------------------------
	 private void getDataPdf() 
	 {
		 NodeList children = null;
		 
		 ///////////////////////////////////////////////////////
		 if(doc != null)
			 children = doc.getElementsByTagName("dataPDF");	    
		 else 
		 {
			 System.err.println("CLASS: XsdToo METHOD: getDataPdf MSG: doc NULL in Xsd Tool");
			 return;
		 }
		 
	if(children != null)		 
		///////////////////////////////////////////////////////
		 for (int i = 0; i < children.getLength(); i++) 
		 {
			Node aNode = children.item(i);
				    	
			//
			//liste.aggiungi_dataPDF_Element(aNode.getNodeName());
			//
			dataPDF_FLAG = true;
			//
			
			if (aNode.hasChildNodes())
				walkNode(aNode);
			else
				printNode(aNode);
		 }
		 
	 }
	 
	 private void getDataPdf(Node theNode) 
	 {
		 //TODO 
	 }
 
	 
	/**
	 * 
	 */
	 public void run() 
	 {
		 //
		 getXDPData();
        
		 try 
		 {
			//
			write_xsd();
		 } 
		 catch (TransformerConfigurationException e) {
			 e.printStackTrace();
		 } 
		 catch (FileNotFoundException e) {
			 e.printStackTrace();
		 } 
		 catch (SAXException e) {
			 e.printStackTrace();
		 }				
	 }
	 
	 /**
	  * 
	  * @param args
	  */
	 public static void main(String[] args)  
	 {
		// istanzia XDP Reader
		//
		//....
		
		//XsdTool xsd_tool = new XsdTool("		");
		//xsd_tool.run();
	 }	
}
